#include "framework/testutil.h"
#include "frontend/lexer.h"
#include <iostream>

using namespace mspc;

TEST("TestLexer", "test_basic_lexer") {
    std::string source = R"(
syntax = "msp/v1";
package example;

struct UserInfo {
    string name = 1;
    int32 age = 2 : 0;
    bool active = 3 : true;
    string branch = 4 : "true";
}

message LoginRequest {
    id = 1001;
    UserInfo user = 1;
    string password = 2;
}

enum Status {
    ACTIVE = 1;
    INACTIVE = 2; // 备注
}
)";

    Lexer lexer(source);
    auto container = lexer.tokenize();
    auto tokens = container.tokens();
    ASSERT_GT(tokens.size(), 2U);
    char buff[6] = {0};
    for (const auto& token : tokens) {
        if (token.type == TokenType::KW_SYNTAX && token.value == "syntax") {
            buff[0] = '1';
        }
        if (token.type == TokenType::KW_STRUCT && token.value == "struct") {
            buff[1] = '1';
        }
        if (token.type == TokenType::IDENTIFIER && token.value == "true") {
            buff[2] = '1';
        }
        if (token.type == TokenType::KW_MESSAGE && token.value == "message") {
            buff[3] = '1';
        }
        if (token.type == TokenType::IDENTIFIER && token.value == "INACTIVE") {
            buff[4] = '1';
        }
        if (token.type == TokenType::IDENTIFIER && (token.value == "//" || token.value == "备注")) {
            buff[5] = '1';
        }
    }
    ASSERT_EQ(memcmp(buff, "11111\0", 6), 0);
}

TEST("TestLexer", "test_line_comments") {
    // 测试用例1：普通单行注释
    std::string source1 = "// 单行注释内容";
    Lexer lexer1(source1, "test1.msp");
    auto container1 = lexer1.tokenize();
    auto tokens1 = container1.tokens();
    ASSERT_TRUE(tokens1.size() == 1); // 只有EOF
    ASSERT_TRUE(tokens1[0].type == TokenType::END_OF_FILE);

    // 测试用例2：包含 / 但不是注释
    std::string source2 = "/ 注释内容";
    Lexer lexer2(source2, "test2.msp");
    auto container2 = lexer2.tokenize();
    auto tokens2 = container2.tokens();
    ASSERT_TRUE(tokens2.size() == 1);
    ASSERT_TRUE(tokens2[0].type == TokenType::ERROR);

    // 测试用例3：//之间插入换行符
    std::string source3 = R"(
 /
/ 

)";
    Lexer lexer3(source3, "test3.msp");
    auto container3 = lexer3.tokenize();
    auto tokens3 = container3.tokens();
    ASSERT_TRUE(tokens3.size() == 1);
    ASSERT_TRUE(tokens3[0].type == TokenType::ERROR);

    // 测试用例4：多个单行注释
    std::string source4 = R"(
// 第一行注释 
// 第二行注释

)";
    Lexer lexer4(source4, "test4.msp");
    auto container4 = lexer4.tokenize();
    auto tokens4 = container4.tokens();
    ASSERT_TRUE(tokens4.size() == 1); // 正常解析
    ASSERT_TRUE(tokens4[0].type == TokenType::END_OF_FILE);
}

TEST("TestLexer", "test_block_comments") {

    // 测试用例1：普通块注释
    std::string source1 = "/* 注释内容 */";
    Lexer lexer1(source1, "test1.msp");
    auto container1 = lexer1.tokenize();
    auto tokens1 = container1.tokens();
    ASSERT_TRUE(tokens1.size() == 1); // 只有EOF
    ASSERT_TRUE(tokens1[0].type == TokenType::END_OF_FILE);

    // 测试用例2：包含 /* 但不是嵌套注释
    std::string source2 = "/* 包含 /* 但不是嵌套 */";
    Lexer lexer2(source2, "test2.msp");
    auto container2 = lexer2.tokenize();
    auto tokens2 = container2.tokens();
    ASSERT_TRUE(tokens2.size() == 1); // 正确解析
    ASSERT_TRUE(tokens2[0].type == TokenType::END_OF_FILE);

    // 测试用例3：多行块注释
    std::string source3 = R"(
/* 第一行
   第二行
   包含 /* 字符
   第三行 */
)";
    Lexer lexer3(source3, "test3.msp");
    auto container3 = lexer3.tokenize();
    auto tokens3 = container3.tokens();
    ASSERT_TRUE(tokens3.size() == 1); // 正确解析
    ASSERT_TRUE(tokens3[0].type == TokenType::END_OF_FILE);

    // 测试用例4：未终止的块注释
    std::string source4 = "/* 未终止的注释";
    Lexer lexer4(source4, "test4.msp");
    auto container4 = lexer4.tokenize();
    auto tokens4 = container4.tokens();
    ASSERT_TRUE(tokens4.size() == 1);
    ASSERT_TRUE(tokens4[0].type == TokenType::ERROR);
}

RUN_ALL_TESTS();
